#ifndef CAMERA_PING_PONG_BUFFER_H
#define CAMERA_PING_PONG_BUFFER_H

#include <atomic>
#include <memory>
#include <cstdint>
#include <cstddef>
#include <mutex>

/**
 * @brief 相机数据乒乓缓冲区实现
 * 
 * 该类实现了单一生产者-消费者模型的乒乓缓冲区机制，适用于相机等实时数据采集场景。
 * 采用两个缓冲区交替使用，实现数据写入和读取的并行处理，减少等待时间。
 * 生产者负责写入数据，消费者负责读取数据，线程安全。
 */
class CameraPingPongBuffer 
{
public:
    /**
     * @brief 构造函数，初始化指定大小的乒乓缓冲区
     * @param buffer_size 每个缓冲区的大小（字节数）
     */
    explicit CameraPingPongBuffer(size_t buffer_size);
    
    /**
     * @brief 析构函数，默认实现
     * 使用了智能指针，无需手动释放内存
     */
    ~CameraPingPongBuffer() = default;
    
    /**
     * @brief 禁用拷贝构造函数
     * 乒乓缓冲区不允许拷贝，避免多线程访问冲突
     */
    CameraPingPongBuffer(const CameraPingPongBuffer&) = delete;
    
    /**
     * @brief 禁用赋值运算符
     * 乒乓缓冲区不允许赋值，避免多线程访问冲突
     */
    CameraPingPongBuffer& operator=(const CameraPingPongBuffer&) = delete;
    
    /**
     * @brief 获取可写入的缓冲区
     * @return 指向可写入缓冲区的指针，若暂时无法获取则返回nullptr
     * @note 由生产者调用，获取空闲缓冲区用于写入数据
     */
    uint8_t* getWriteBuffer();
    
    /**
     * @brief 提交写入完成的数据
     * @param data_size 实际写入的数据大小（字节数）
     * @return 提交成功返回true，失败返回false
     * @note 由生产者调用，标记缓冲区为就绪状态，供消费者读取
     */
    bool commitWrite(size_t data_size);
    
    /**
     * @brief 获取可读取的缓冲区
     * @param[out] data_size 输出参数，返回实际有效数据大小（字节数）
     * @return 指向可读取缓冲区的const指针，若无可读数据则返回nullptr
     * @note 由消费者调用，获取就绪状态的缓冲区用于读取数据
     */
    const uint8_t* getReadBuffer(size_t& data_size);
    
    /**
     * @brief 完成读取操作
     * @note 由消费者调用，标记缓冲区为空闲状态，供生产者再次使用
     */
    void finishRead();
    
    /**
     * @brief 获取缓冲区大小
     * @return 每个缓冲区的大小（字节数）
     */
    size_t getBufferSize() const { return buffer_size_; }
    
    /**
     * @brief 检查是否有可读数据
     * @return 有可读数据返回true，否则返回false
     */
    bool hasReadableData() const;

private:
    /**
     * @brief 缓冲区状态枚举
     * 用于跟踪每个缓冲区的生命周期状态，确保线程安全的访问
     */
    enum class BufferState : int {
        IDLE = 0,      // 缓冲区空闲，可以被分配为写缓冲区
        WRITING = 1,   // 正在被写入（生产者持有）
        READY = 2,     // 数据就绪，等待读取（已完成写入）
        READING = 3    // 正在被读取（消费者持有）
    };
    
    /**
     * @brief 缓冲区结构体
     * 包含实际数据存储、数据大小和状态信息
     */
    struct Buffer 
    {
        /**
         * @brief 缓冲区数据存储
         * 使用智能指针管理动态分配的字节数组
         */
        std::unique_ptr<uint8_t[]> data;
        
        /**
         * @brief 有效数据大小
         * 原子变量，记录当前缓冲区中实际有效的数据字节数
         */
        std::atomic<size_t> data_size{0};
        
        /**
         * @brief 缓冲区状态
         * 原子变量，跟踪缓冲区当前的状态（IDLE/WRITING/READY/READING）
         */
        std::atomic<BufferState> state{BufferState::IDLE};
        
        /**
         * @brief 缓冲区构造函数
         * @param size 缓冲区大小（字节数）
         */
        explicit Buffer(size_t size);
    };
    
    /**
     * @brief 每个缓冲区的大小（字节数）
     * 所有缓冲区大小相同，在构造时确定
     */
    const size_t buffer_size_;
    
    /**
     * @brief 缓冲区A
     * 乒乓缓冲区中的第一个缓冲区
     */
    std::unique_ptr<Buffer> buffer_a_;
    
    /**
     * @brief 缓冲区B
     * 乒乓缓冲区中的第二个缓冲区
     */
    std::unique_ptr<Buffer> buffer_b_;
    
    /**
     * @brief 缓冲区操作互斥锁
     * 保护缓冲区指针的分配和切换，确保线程安全
     * 声明为mutable以允许在const成员函数中使用
     */
    mutable std::mutex buffer_mutex_;
    
    /**
     * @brief 当前写缓冲区指针
     * 指向当前分配给生产者用于写入的缓冲区
     */
    Buffer* current_write_buffer_;
    
    /**
     * @brief 当前读缓冲区指针
     * 指向当前可供消费者读取的缓冲区
     */
    Buffer* current_read_buffer_;
};

#endif // CAMERA_PING_PONG_BUFFER_H